home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Frameworks / MacZoop 1.6.5 / Basic Classes / Z Sources / CursorUtilities.c next >
Encoding:
C/C++ Source or Header  |  1997-07-16  |  8.8 KB  |  354 lines  |  [TEXT/MPCC]

  1. /*************************************************************************************************
  2. *
  3. *
  4. *        CursorUtilities.c            - cursor stuff- spinning watch, etc
  5. *
  6. *        26/9/94        ©1994, Graham Cox
  7. *
  8. *        This code based on "Macintosh Programming Secrets" 2nd Edition by Keith Rollin & Scott K
  9. *
  10. *************************************************************************************************/
  11.  
  12. #include    "CursorUtilities.h"
  13.  
  14. #include    <LowMem.h>
  15.  
  16. short                gVBLCount;
  17. VBLTaskWithA5Ptr    gCursorTask = NULL;
  18.  
  19. acurHdl                gWatchSpinner = NULL;
  20. acurHdl                gBallSpinner = NULL;
  21.  
  22. // macro for doing dodgy 68000 stuff!
  23.  
  24. #ifndef __powerc
  25.     VBLTaskWithA5Ptr    GetVBLRec(void) = 0x2008;
  26. #endif
  27.  
  28. static Handle    GetDetachedResource(ResType aType, short anID);
  29.  
  30. /*-------------------------***  GETDETACHEDRESOURCE  ***--------------------------------*/
  31. /*    
  32.  
  33. returns a detched resourse with type and ID passed.
  34.  
  35. ----------------------------------------------------------------------------------------*/
  36.  
  37. static Handle    GetDetachedResource(ResType aType, short anID)
  38. {
  39.     Handle    temp = NULL;
  40.     
  41.     temp = GetResource(aType,anID);
  42.     
  43.     if (temp)
  44.         DetachResource(temp);
  45.  
  46.     return temp;
  47. }
  48.  
  49. /*--------------------------***  INITANIMATEDCURSOR  ***--------------------------------*/
  50. /*    
  51.  
  52. sets up an animated cursor by reading the 'acur' resource with the ID passed.
  53.  
  54. ----------------------------------------------------------------------------------------*/
  55.  
  56. acurHdl        InitAnimatedCursor(short resID)
  57. {
  58.     acurHdl        temp;
  59.     short        ccount;
  60.     CursHandle    aCursor;
  61.     CursHandle*    workPtr;
  62.     
  63.     temp = (acurHdl) GetDetachedResource('acur',resID);
  64.     
  65.     if (temp)
  66.     {
  67.         ccount = (*temp)->numCursors;
  68.         (*temp)->numCursors *= 32;
  69.         (*temp)->index = 0;
  70.         
  71.         HLock((Handle) temp);
  72.         workPtr = (*temp)->cursors;
  73.         
  74.         while(ccount--)
  75.         {
  76.             aCursor = (CursHandle) GetDetachedResource('CURS',*(short*) workPtr);
  77.             *workPtr++ = aCursor; 
  78.         }    
  79.         HUnlock((Handle) temp);
  80.     }
  81.     return(temp);
  82. }
  83.  
  84.  
  85.  
  86. /*-------------------------***  STARTCURSORANIMATION  ***-------------------------------*/
  87. /*    
  88. sets up the VBL queue to animate the cursor passed.
  89.  
  90. ----------------------------------------------------------------------------------------*/
  91.  
  92. void        StartCursorAnimation(short period, acurHdl theCursor)
  93. {
  94.     // primes the VBL queue to spin the cursor automatically
  95.     
  96.     VBLUPP        vTaskUPP;
  97.     
  98.     if (theCursor)
  99.     {
  100.         LockCursorData(theCursor);
  101.     
  102.         gVBLCount = period;
  103.         gCursorTask = (VBLTaskWithA5Ptr) NewPtr(sizeof(VBLTaskWithA5));
  104.         
  105.         gCursorTask->theTask.qType = vType;
  106.         
  107.         vTaskUPP = NewVBLProc((ProcPtr) VBLCursorSpin);
  108.         
  109.         gCursorTask->theTask.vblAddr = vTaskUPP;
  110.         gCursorTask->theTask.vblCount = period;
  111.         gCursorTask->theTask.vblPhase = 0;
  112.         gCursorTask->A5 = (long) LMGetCurrentA5();
  113.         gCursorTask->theCursor = theCursor;
  114.         
  115.         (void) VInstall((QElemPtr) gCursorTask);
  116.     }
  117. }
  118.  
  119.  
  120. /*-------------------------***  STOPCURSORANIMATION  ***--------------------------------*/
  121. /*    
  122.  
  123. Kills the current cursor in the VBL queue and unlocks it. This then restores the arrow.
  124. ----------------------------------------------------------------------------------------*/
  125.  
  126. void        StopCursorAnimation(void)
  127. {
  128.     // removes spinning cursor task from the VBL queue
  129.     
  130.     acurHdl        theCursor;
  131.     
  132.     if (gCursorTask)
  133.     {
  134.         (void) VRemove((QElemPtr) gCursorTask);
  135.         
  136.         theCursor = gCursorTask->theCursor;
  137.         DisposeRoutineDescriptor(gCursorTask->theTask.vblAddr);
  138.         
  139.         DisposePtr((Ptr) gCursorTask);
  140.         gCursorTask = NULL;
  141.         UnlockCursorData(theCursor);
  142.         
  143.         SetCursor( &qd.arrow );
  144.     }
  145. }
  146.  
  147.  
  148. /*-----------------------------***  ANIMATECURSOR  ***----------------------------------*/
  149. /*    
  150.  
  151. Can be called repeatedly to animate a cursor. However, it is simpler to let the VBL task
  152. do this in general.
  153.  
  154. ----------------------------------------------------------------------------------------*/
  155.  
  156. void        AnimateCursor(short increment,acurHdl theCursor)
  157. {
  158.     // used only for non-VBL cursor spinning
  159.     
  160.     short        oldIndex,newIndex;
  161.     CursHandle    aCursor;
  162.     
  163.     if (theCursor)
  164.     {
  165.         oldIndex = (*theCursor)->index / 32;
  166.         
  167.         (*theCursor)->index += increment;
  168.         (*theCursor)->index %= (*theCursor)->numCursors;
  169.         
  170.         newIndex = (*theCursor)->index / 32;
  171.         
  172.         if (newIndex != oldIndex)
  173.         {
  174.             aCursor = (*theCursor)->cursors[newIndex];
  175.             SetCursor(*aCursor);
  176.         }
  177.     }
  178. }
  179.  
  180.  
  181. /*----------------------------***  LOCKCURSORDATA  ***----------------------------------*/
  182. /*    
  183.  
  184. locks down the cursor handles ready for animation
  185.  
  186. ----------------------------------------------------------------------------------------*/
  187.  
  188. void        LockCursorData(acurHdl theCursor)
  189. {
  190.     // locks the cursor and its internal data
  191.     
  192.     short        ccount;
  193.     CursHandle    *workPtr;
  194.     
  195.     ccount = (*theCursor)->numCursors / 32;
  196.     
  197.     HLockHi((Handle) theCursor);
  198.     workPtr = (*theCursor)->cursors;
  199.     
  200.     while (ccount--)
  201.         HLockHi((Handle) *workPtr++);    
  202. }
  203.  
  204.  
  205. /*--------------------------***  UNLOCKCURSORDATA  ***----------------------------------*/
  206. /*    
  207.  
  208. unlocks the cursor handles
  209. ----------------------------------------------------------------------------------------*/
  210.  
  211. void        UnlockCursorData(acurHdl theCursor)
  212. {
  213.     // unlocks the cursor
  214.     
  215.     short        ccount;
  216.     CursHandle    *workPtr;
  217.     
  218.     ccount = (*theCursor)->numCursors / 32;
  219.     workPtr = (*theCursor)->cursors;
  220.     
  221.     while (ccount--)
  222.         HUnlock((Handle) *workPtr++);    
  223.  
  224.     HUnlock((Handle) theCursor);
  225. }
  226.  
  227. /*-----------------------------***  VBLCURSORSPIN  ***----------------------------------*/
  228. /*    
  229.  
  230. this is the VBL callback that actually performs the animation of a VBL-driven cursor
  231. ----------------------------------------------------------------------------------------*/
  232.  
  233. #ifndef __powerc
  234.     void        VBLCursorSpin()
  235. #else
  236.     void        VBLCursorSpin(VBLTaskWithA5Ptr theTask)
  237. #endif
  238. {
  239.     // this is the function that is called from the interrupt task. 
  240.     
  241.     acurHdl        theCrsr;
  242.     long        oldA5;
  243.     
  244. #ifndef __powerc
  245.     VBLTaskWithA5Ptr    theTask;
  246.     
  247.     theTask = GetVBLRec();
  248.     oldA5 = SetA5(theTask->A5);
  249.     if (LMGetCrsrBusy() == 0)
  250.     {
  251.         theCrsr = theTask->theCursor;
  252.         AnimateCursor(32,theCrsr);
  253.     }
  254.     theTask->theTask.vblCount = gVBLCount;
  255.     (void) SetA5(oldA5);
  256.     
  257. #else
  258.     oldA5 = SetA5(theTask->A5);
  259.         
  260.     if (LMGetCrsrBusy() == 0)
  261.     {
  262.         theCrsr = theTask->theCursor;
  263.         AnimateCursor(32,theCrsr);
  264.     }
  265.     theTask->theTask.vblCount = gVBLCount;
  266.     (void) SetA5(oldA5);
  267. #endif
  268. }
  269.  
  270.  
  271. /*-----------------------------***  SETWATCHCURSOR  ***---------------------------------*/
  272. /*    
  273.  
  274. starts the animated watch cursor. To stop it, call StopCursorAnimation.
  275. ----------------------------------------------------------------------------------------*/
  276.  
  277. void        SetWatchCursor()
  278. {
  279.     // HL call installs VBL spinner for watch, which should have been inited beforehand
  280.     
  281.     if (gWatchSpinner && ! gCursorTask)
  282.         StartCursorAnimation(8, gWatchSpinner);
  283. }
  284.  
  285. /*---------------------------***  SETBEACHBALLCURSOR  ***-------------------------------*/
  286. /*    
  287.  
  288. starts the animated "beachball" cursor. To stop it, call StopCursorAnimation.
  289. ----------------------------------------------------------------------------------------*/
  290.  
  291. void        SetBeachBallCursor()
  292. {
  293.     if (gBallSpinner && ! gCursorTask)
  294.         StartCursorAnimation(4, gBallSpinner);
  295.  
  296. }
  297.  
  298. /*-------------------------------***  GETMODIFIERS  ***---------------------------------*/
  299. /*    
  300.  
  301. can be called at any time to get the current state of the keyboard modifier keys. Useful
  302. if the cursor is changed with different modifiers down.
  303. ----------------------------------------------------------------------------------------*/
  304.  
  305. short        GetModifiers()
  306. {
  307.     // returns the current state of the modifier keys as if it was the modifier field in
  308.     // an event record. This can be called at any time, even when an event is not available.
  309.     // It is very useful for updating the cursor to show the modifier state.
  310.     
  311.     unsigned char    theKeys[16];
  312.     short            modifiers;
  313.     
  314.     
  315.     GetKeys((UInt32*) theKeys);
  316.     
  317.     modifiers = 0;
  318.     
  319.     ((theKeys[0x37 >> 3] >> (0x37 & 7)) & 1)? modifiers |= cmdKey : 0;
  320.     ((theKeys[0x38 >> 3] >> (0x38 & 7)) & 1)? modifiers |= shiftKey : 0;
  321.     ((theKeys[0x39 >> 3] >> (0x39 & 7)) & 1)? modifiers |= alphaLock : 0;
  322.     ((theKeys[0x3A >> 3] >> (0x3A & 7)) & 1)? modifiers |= optionKey : 0;
  323.     ((theKeys[0x3B >> 3] >> (0x3B & 7)) & 1)? modifiers |= controlKey : 0;
  324.  
  325.     (! Button())? modifiers |= btnState : 0;
  326.     
  327.     return modifiers;
  328. }
  329.  
  330.  
  331. /*------------------------------***  APPCURSORINIT  ***---------------------------------*/
  332. /*    
  333. high-level call to initialise the two animated cursors. Extend this for others you may have
  334. ----------------------------------------------------------------------------------------*/
  335.  
  336. void        AppCursorInit()
  337. {
  338.     // called once at application start-up to initialise the animated cursor globals.
  339.  
  340.     gWatchSpinner = InitAnimatedCursor(kWatchResID);
  341.     gBallSpinner = InitAnimatedCursor(kBeachBallResID);
  342. }
  343.  
  344. /*------------------------------***  CURSORANIMATING  ***-------------------------------*/
  345. /*    
  346. returns TRUE if an animated cursor is on screen. You should not call
  347. SetCursor if this is true, or ugly cursor flickering occurs.
  348. ----------------------------------------------------------------------------------------*/
  349.  
  350. Boolean        CursorAnimating()
  351. {
  352.     return (gCursorTask != NULL);
  353. }
  354.